﻿
namespace FolderSync
{
    using System;
    using System.IO;
    public class InvalidPathException : ApplicationException {
        public InvalidPathException(string message)
            : base(message)
        {
        }
    }
    public static class IOObjectsExtensions
    {
        public static bool IsReparsePoint(this DirectoryInfo d)
        {
            return d.Exists
                && d.Attributes.HasFlag(FileAttributes.Directory)
                && d.Attributes.HasFlag(FileAttributes.ReparsePoint);
        }
        public static string EnsureFolderExists(this string path, bool create = false)
        {
            var d = new DirectoryInfo(path).EnsureExists(create);
            return d == null ? null : d.FullName;
        }
        public static DirectoryInfo EnsureExists(this DirectoryInfo d, bool create = false)
        {
            if (d == null) throw new InvalidPathException("DirectoryInfo.EnsureExists: Null DirectoryInfo object");
            if (!d.Root.Exists) throw new InvalidPathException("DirectoryInfo.EnsureExists: Invalid DirectoryInfo root");
            if (!d.Exists)
            {
                if (create)
                {
                    EnsureExists(d.Parent, create);
                    try
                    {
                        d.Create();
                    }
                    catch {
                        throw;
                    }
                }
                else return null;
            }
            return d;
        }
        public static FileInfo LogFileinfo(this ConfigurationSet configset, bool dated = true)
        {
            if (string.IsNullOrWhiteSpace(configset.Logfile)) return null;

            var fi = new FileInfo(configset.Logfile);
            var _logfile = !dated
                ? fi
                : new FileInfo(string.Format("{0}\\{1}_{2}{3}",
                        fi.DirectoryName,
                        fi.Name,
                        string.Format("_{0}", DateTime.Now.ToString("yyyyMMdd_HHmmss.ff")),
                        fi.Extension
                    ));
            if (string.IsNullOrWhiteSpace(_logfile.Directory.EnsureExists(true).Name))
            {
                throw new Exception(string.Format("Unable to open log folder :«{0}»", configset.Logfile));
            }
            return _logfile;
        }
        public static Boolean NotifyCopyTo(this FileInfo fi, string path, Func<float, bool> notifyProgress, int blocksize = 1048576)
        {
                var buffer = new byte[blocksize];
                long bytesTotal = 0;
                int bytesRead = -1;
                float bytesTarget = fi.Length;
                var fiTrg = new FileInfo(path);
                fiTrg.Directory.EnsureExists(create: true);
                if (fiTrg.Exists) fiTrg.Delete();
                using (var src = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (var trg = fiTrg.OpenWrite())
                    {
                        while (bytesRead != 0
                            && (notifyProgress == null || notifyProgress(bytesTotal / bytesTarget))
                            )
                        {
                            bytesRead = src.Read(buffer, 0, blocksize);
                            bytesTotal += bytesRead;
                            trg.Write(buffer, 0, bytesRead);
                        }
                        trg.Close();
                        src.Close();
                        return true;
                    }
                }
        }
    }
}
